home *** CD-ROM | disk | FTP | other *** search
- /*
- * mosaic.c
- * kirk johnson
- * october 1990
- */
-
- #include "mosaic.h"
- #include <X11/Xos.h>
- #include <pwd.h>
-
- #ifdef LOGGING
- static FILE *logfile;
- static void OpenLogFile();
- #endif
-
- Word tile[NTiles]; /* the board */
- Word piece[NPieces]; /* the "deck" of pieces */
- Word nextpiece; /* index into the deck */
-
- Word size[NTiles]; /* score data structures */
- Word parent[NTiles];
-
- Word tscore[3]; /* total score */
- Word pscore[3]; /* last piece score */
- Word remain[3]; /* tiles remaining */
-
- NameAndScore highscore[NHighScores];
- short UseHighScore = 1;
-
-
- main(argc, argv)
- int argc;
- char **argv;
- {
- ReadHighScores();
- InitGame();
- InitDisplay(argc, argv);
- #ifdef LOGGING
- OpenLogFile();
- #endif
- MainLoop();
- }
-
-
- void InitGame()
- {
- int i, j, k, l;
- int idx, swap;
-
- /* randomize */
- srand48((long)time((long *)0));
-
- /* clear the board */
- for (i=0; i<NTiles; i++)
- tile[i] = 0;
-
- /* set up deck */
- idx = 0;
- for (i=1; i<=3; i++)
- for (j=1; j<=3; j++)
- for (k=1; k<=3; k++)
- for (l=1; l<=3; l++)
- piece[idx++] = (i<<6) | (j<<4) | (k<<2) | (l<<0);
-
- /* shuffle */
- for (i=0; i<1000; i++)
- {
- idx = lrand48() % NPieces;
- swap = piece[idx];
- piece[idx] = piece[0];
- piece[0] = swap;
- }
- nextpiece = 0;
-
- /* clear score data structures */
- for (i=0; i<NTiles; i++)
- {
- size[i] = 1;
- parent[i] = i;
- }
-
- for (i=0; i<3; i++)
- {
- tscore[i] = 0;
- pscore[i] = 0;
- remain[i] = (NPieces * 4) / 3;
- }
- }
-
-
- void QuitGame()
- {
- exit(0);
- }
-
-
- int DropPiece(r, c, p)
- int r, c;
- Word p;
- {
- int idx;
- Word type;
- Word nscore[3];
-
- idx = r * BoardSize + c;
-
- /* check for illegal move */
- if ((tile[idx] != 0) ||
- (tile[idx+1] != 0) ||
- (tile[idx+BoardSize] != 0) ||
- (tile[idx+BoardSize+1] != 0))
- return 0;
-
- /* place the piece */
- type = p & 0x03;
- tile[idx] = type;
- remain[type-1] -= 1;
- p >>= 2;
-
- type = p & 0x03;
- tile[idx+1] = type;
- remain[type-1] -= 1;
- p >>= 2;
-
- type = p & 0x03;
- tile[idx+BoardSize] = type;
- remain[type-1] -= 1;
- p >>= 2;
-
- type = p & 0x03;
- tile[idx+BoardSize+1] = p & 0x03;
- remain[type-1] -= 1;
-
- /* update the score */
- UpdateAndScore(r, c, nscore);
- for (idx=0; idx<3; idx++)
- {
- pscore[idx] = nscore[idx] - tscore[idx];
- tscore[idx] = nscore[idx];
- }
-
- /* redraw */
- drawTile(r++, c);
- drawTile(r, c++);
- drawTile(r--, c);
- drawTile(r, c--);
- drawController();
- drawScore();
-
- return 1;
- }
-
-
- void UpdateAndScore(r, c, score)
- int r, c;
- Word score[];
- {
- int i;
-
- i = r * BoardSize + c;
-
- PossiblyMerge(i, i+1);
- PossiblyMerge(i+BoardSize, i+BoardSize+1);
-
- PossiblyMerge(i, i+BoardSize);
- PossiblyMerge(i+1, i+BoardSize+1);
-
- if (c >= 1)
- {
- PossiblyMerge(i, i-1);
- PossiblyMerge(i+BoardSize, i+BoardSize-1);
- }
-
- if (r >= 1)
- {
- PossiblyMerge(i, i-BoardSize);
- PossiblyMerge(i+1, i-BoardSize+1);
- }
-
- if (c <= (BoardSize-3))
- {
- PossiblyMerge(i+1, i+2);
- PossiblyMerge(i+BoardSize+1, i+BoardSize+2);
- }
-
- if (r <= (BoardSize-3))
- {
- PossiblyMerge(i+BoardSize, i+(2*BoardSize));
- PossiblyMerge(i+BoardSize+1, i+(2*BoardSize)+1);
- }
-
- /* compute the new score */
- for (i=0; i<3; i++)
- score[i] = 0;
- for (i=0; i<NTiles; i++)
- if ((tile[i] != 0) && (parent[i] == i))
- score[tile[i]-1] += size[i] * size[i];
- }
-
-
- void PossiblyMerge(i, j)
- int i, j;
- {
- Word irep;
- Word jrep;
- Word scan;
-
- /* tiles are not the same color */
- if (tile[i] != tile[j]) return;
-
- /* find i's rep */
- irep = i;
- while (parent[irep] != irep)
- irep = parent[irep];
-
- /* compress path from i to irep */
- scan = i;
- while (parent[scan] != scan)
- {
- scan = parent[scan];
- parent[scan] = irep;
- }
-
- /* find j's rep */
- jrep = j;
- while (parent[jrep] != jrep)
- jrep = parent[jrep];
-
- /* compress path from j to jrep */
- scan = j;
- while (parent[scan] != scan)
- {
- scan = parent[scan];
- parent[scan] = jrep;
- }
-
- /* tiles are already in the same set */
- if (irep == jrep) return;
-
- /* merge the sets */
- if (size[irep] > size[jrep])
- {
- parent[jrep] = irep;
- size[irep] += size[jrep];
- }
- else
- {
- parent[irep] = jrep;
- size[jrep] += size[irep];
- }
- }
-
-
- void AutoPlay()
- {
- int r, c;
-
- while (nextpiece < NPieces)
- {
- do
- {
- r = lrand48() % (BoardSize-1);
- c = lrand48() % (BoardSize-1);
- }
- while (!DropPiece(r, c, piece[nextpiece]));
-
- nextpiece += 1;
- drawNext();
-
- if (UseHighScore && (nextpiece == NPieces))
- CheckHighScore();
- }
- }
-
-
- void ReadHighScores()
- {
- int i;
- FILE *s;
-
- s = fopen(ScoreFile, "r");
- if (s == NULL)
- {
- warning("unable to open score file; attempting to create new one");
-
- for (i=0; i<NHighScores; i++)
- {
- strcpy(highscore[i].uname, ".");
- highscore[i].score = -1;
- }
-
- s = fopen(ScoreFile, "w");
- if (s == NULL) {
- warning("unable to create score file");
- UseHighScore = 0;
- }
- else {
- WriteHighScores();
- fclose(s);
-
- if (chmod(ScoreFile, 0777) != 0)
- {
- unlink(ScoreFile);
- fatal("unable to set score file mode");
- }
- }
- }
- else
- {
- for (i=0; i<NHighScores; i++)
- if (fscanf(s, "%s %d",
- highscore[i].uname, &highscore[i].score) != 2)
- fatal("incomplete score file read");
- fclose(s);
- }
- }
-
-
- void WriteHighScores()
- {
- int i;
- FILE *s;
-
- s = fopen(ScoreFile, "w");
- if (s == NULL) {
- warning("unable to open score file");
- UseHighScore = 0;
- }
- else {
- for (i=0; i<NHighScores; i++)
- fprintf(s, "%s %d\n", highscore[i].uname, highscore[i].score);
- }
- fclose(s);
- }
-
-
- void CheckHighScore()
- {
- int i;
- int score;
- char *uname;
-
- uname = getpwuid(getuid())->pw_name;
- score = tscore[0] + tscore[1] + tscore[2];
-
- /*
- * note that we don't actually try to do any locking of
- * the high score file during this critical section ...
- */
-
- ReadHighScores();
-
- for (i=0; i<NHighScores; i++)
- if (strcmp(highscore[i].uname, uname) == 0)
- break;
-
- if (i == NHighScores)
- i = NHighScores - 1;
-
- if (score > highscore[i].score)
- {
- while ((i > 0) && (score > highscore[i-1].score))
- {
- strcpy(highscore[i].uname, highscore[i-1].uname);
- highscore[i].score = highscore[i-1].score;
- i -= 1;
- }
- strcpy(highscore[i].uname, uname);
- highscore[i].score = score;
-
- WriteHighScores();
- }
-
- drawHighScores();
-
- #ifdef LOGGING
- /*
- * because we don't catch this and die when we open the file; add
- * the check here. ah well.
- */
- if (logfile != NULL)
- {
- putc(1, logfile);
- fflush(logfile);
- }
- #endif
- }
-
-
- warning(msg)
- char *msg;
- {
- fflush(stdout);
- fprintf(stderr, "%s: warning! %s\n", AppName, msg);
- fflush(stderr);
- }
-
-
- fatal(msg)
- char *msg;
- {
- fflush(stdout);
- fprintf(stderr, "%s: %s\n", AppName, msg);
- exit(1);
- }
-
-
- #ifdef LOGGING
- static void OpenLogFile()
- {
- char hostname[256];
- char logname[256];
-
- if (gethostname(hostname, 256) != 0)
- {
- #ifdef DEBUG
- warning("unable to get hostname");
- #endif
- return;
- }
-
- sprintf(logname, "%s/%08X.%s.%d", LogDir, time(NULL), hostname, getuid());
- logfile = fopen(logname, "w");
- if (logfile == NULL)
- {
- #ifdef DEBUG
- warning("problems opening logfile");
- #endif
- return;
- }
- }
- #endif
-